package view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.management.ManagementPermission;

import java.util.List;


import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.TransferHandler;


import com.mxgraph.examples.swing.GraphEditor;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.swing.util.mxGraphActions;
import com.mxgraph.util.mxResources;
import com.mxgraph.view.mxGraph;
import com.mxgraph.examples.swing.editor.EditorActions.*;


import model.Atributo;
import model.AtributoCompuesto;
import model.Coordenada;
import model.Entidad;
import model.Jerarquia;
import model.Proyecto;
import model.Relacion;

import view.accciones.ValidarProyecto;
import view.entidad.GlobalEntidadDialogo;
import view.entidad.NuevaEntidadDialogo;
import view.entidad.NuevaJerarquiaDialogo;

import view.entidad.NuevoDiagramaDialogo;
import view.relacion.NuevaRelacionDialogo;

import constants.PantallaConstants;
import controller.ManagerAreaDeTrabajo;
import controller.ManagerProyecto;
import controller.ManagerExportar;
import controller.ManagerRelacion;

public class Pantalla {

	private static Pantalla pantalla = new Pantalla();
	private JFrame mainFrame;
	private JMenuBar menuBar;
	
	
	private GraphEditor areaDeTrabajo;
	private ElegidorDeArchivos elegidorArchivo;
	private ExploradorDeDiagramas packageExplorer;
	private ManagerProyecto controlProyeto;
	

	private JScrollPane scrollPackage;

	public static Pantalla getPantalla() {
		return pantalla;
	}

	public void setManagerProyecto(ManagerProyecto controlProyeto) {
		this.controlProyeto = controlProyeto;
	}
	
	public ManagerProyecto getManagerProyeto() {
		return controlProyeto;
	}

	private Pantalla() {
		mainFrame = new JFrame(PantallaConstants.NOMBRE_HERRAMIENTA);
		mainFrame.setIconImage(new ImageIcon(PantallaConstants.IMAGEN_HERRAMIENTA).getImage());
		mainFrame.setSize(800, 600);
		mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		mainFrame.setExtendedState(Frame.MAXIMIZED_BOTH);
		mainFrame.setResizable(true);
	}

	public void crearPantalla() {
        
		areaDeTrabajo = new GraphEditor();
		this.agregarBarraHerramientas();
		this.agregarPackageExplorer();

		mainFrame.getContentPane().setBackground(Color.GRAY);
		mainFrame.setVisible(true);
		// mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
		// mainFrame.setResizable(true);
	}

	private void agregarBarraHerramientas() {
		// agrego la barra de herramientas a la ventana principal
		menuBar = new JMenuBar();
		mainFrame.setJMenuBar(menuBar);
		this.agregarMenuArchivoAHerramientas();

	}

	private void agregarMenuEntidadABarraHerramientas() {

		JMenu entidadMenu = new JMenu(PantallaConstants.MENU_ENTIDAD);
		menuBar.add(entidadMenu);

		JMenuItem globalMenuItem = new JMenuItem(PantallaConstants.ENTIDAD_GLOBAL);
		entidadMenu.add(globalMenuItem);
		globalMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				GlobalEntidadDialogo entidadDialogo = new GlobalEntidadDialogo(
						controlProyeto.getProyecto(), controlProyeto.getDiagramaEnPantalla());
				if (entidadDialogo.isLimiteExcedido() == false){
					entidadDialogo.setVisible(true);
					
					packageExplorer.actualizar(controlProyeto.getProyecto().getIdentificator(),
							controlProyeto.getProyecto().getListaDiagramas(),
							controlProyeto.getDiagramaEnPantalla().getIdentificator(), controlProyeto.getDiagramaEnPantalla().getListaEntidades());
				}
					
			}
		});
		entidadMenu.addSeparator();

		JMenuItem nuevaEntidadMenuItem = new JMenuItem(PantallaConstants.ENTIDAD_NUEVA);
		entidadMenu.add(nuevaEntidadMenuItem);

		nuevaEntidadMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ae) {
				NuevaEntidadDialogo entidadDialogo = new NuevaEntidadDialogo(
						controlProyeto.getProyecto(), controlProyeto.getDiagramaEnPantalla());
				if (entidadDialogo.isLimiteExcedido() == false){
					entidadDialogo.setVisible(true);
					
					packageExplorer.actualizar(controlProyeto.getProyecto().getIdentificator(),
							controlProyeto.getProyecto().getListaDiagramas(),
							controlProyeto.getDiagramaEnPantalla().getIdentificator(), controlProyeto.getDiagramaEnPantalla().getListaEntidades());
				}
			}
		});

	}

	private void agregarMenuRelacionABarraHerramientas() {

		JMenu menuRelacion = new JMenu(PantallaConstants.MENU_RELACION);
		menuBar.add(menuRelacion);
		
		JMenuItem relacionBoton = new JMenuItem(PantallaConstants.RELACION_NUEVA);
		relacionBoton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				NuevaRelacionDialogo relacionDialogo = new NuevaRelacionDialogo(controlProyeto.getProyecto(), controlProyeto.getDiagramaEnPantalla());
				relacionDialogo.setVisible(true);
				
			}
		});
		
		menuRelacion.add(relacionBoton);

	}

	private void agregarMenuJerarquiaABarraHerramientas() {

		JMenu jerarquiaMenu = new JMenu(PantallaConstants.MENU_JERARQUIA);
		menuBar.add(jerarquiaMenu);
		
		JMenuItem jerarquiaBoton = new JMenuItem(PantallaConstants.JERARQUIA_NUEVA);
		jerarquiaBoton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				NuevaJerarquiaDialogo jerarquiaDialogo = new NuevaJerarquiaDialogo(controlProyeto.getProyecto(), controlProyeto.getDiagramaEnPantalla());
				jerarquiaDialogo.setVisible(true);
				
			}
		});

		jerarquiaMenu.add(jerarquiaBoton);
	}

	private void agregarMenuValidarABarraHerramientas() {

		JMenu validarMenu = new JMenu(PantallaConstants.MENU_VALIDAR_DIAGRAMA);
		menuBar.add(validarMenu);
		
		JMenuItem validadorBoton = new JMenuItem(PantallaConstants.VALIDAR_PROYECTO);
		
		/*validadorBoton.addActionListener(controlProyeto
				.getListenerBotonGuardar());
		*/
		validadorBoton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				controlProyeto.persistirXML();
				controlProyeto.validarProyeco();
			}
		});

		validarMenu.add(validadorBoton);
		

	}
	
	private void agregarMenuDiagramaABarraHerramientas() {

		JMenu diagrmaMenu = new JMenu("Diagrama");
		menuBar.add(diagrmaMenu);
		
		JMenuItem diagramaBoton = new JMenuItem(PantallaConstants.DIAGRAMA_NUEVO);
		diagramaBoton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				NuevoDiagramaDialogo diagramaDialogo = new NuevoDiagramaDialogo(controlProyeto.getProyecto(), controlProyeto.getDiagramaEnPantalla());
			}
		});
		
		diagrmaMenu.add(diagramaBoton);
		
		

	}

	private void agregarMenuArchivoAHerramientas() {
		// Genero el boton Archivo y lo agrego a la barra de herramientas
		JMenu fileMenu = new JMenu(PantallaConstants.MENU_ARCHIVO);
		menuBar.add(fileMenu);

		// agrego la opcion Abrir al menu de archivo y su Listener
		JMenuItem openMenuItem = new JMenuItem(PantallaConstants.ABRIR_MENU, new ImageIcon("TPDER\\com\\mxgraph\\examples\\swing\\images\\open.gif"));
		fileMenu.add(openMenuItem);
		

		openMenuItem.addActionListener(controlProyeto.getListenerBotonAbrir());

		// agrego la opcion Nuevo al menu de archivo y su Listener
		JMenuItem nuevoMenuItem = new JMenuItem(PantallaConstants.NUEVO_PROYECTO, new ImageIcon("TPDER\\com\\mxgraph\\examples\\swing\\images\\new.gif"));
		fileMenu.add(nuevoMenuItem);

		nuevoMenuItem.addActionListener(controlProyeto
				.getListenerBotonNuevoProyecto());

		// agrego la opcion Nuevo al menu de archivo y su Listener
		JMenuItem guardarMenuItem = new JMenuItem(PantallaConstants.GUARDAR, new ImageIcon("TPDER\\com\\mxgraph\\examples\\swing\\images\\save.gif"));
		fileMenu.add(guardarMenuItem);

		guardarMenuItem.addActionListener(controlProyeto
				.getListenerBotonGuardar());

		// agrego un separador al menu de archivo
		fileMenu.addSeparator();

		// agrego la opcion Configurar Pagina al menu de archivo
		fileMenu.add(areaDeTrabajo.bind(mxResources.get("pageSetup"),
				new PageSetupAction(),
				"/com/mxgraph/examples/swing/images/pagesetup.gif"));

		// agrego la opcion Imprimir al menu de archivo
		fileMenu.add(areaDeTrabajo.bind(mxResources.get("print"),
				new PrintAction(),
				"/com/mxgraph/examples/swing/images/print.gif"));

		// agrego la opcion Exportar al menu de archivo y su Listener
		JMenuItem exportMenuItem = new JMenuItem(PantallaConstants.EXPORTAR, new ImageIcon("TPDER\\com\\mxgraph\\examples\\swing\\images\\exportar.png"));
		fileMenu.add(exportMenuItem);

		exportMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ae) {
				ManagerExportar manager = new ManagerExportar();
				try {
					manager.capturarPantalla(controlProyeto.getProyecto()
							.getPath(), controlProyeto.getDiagramaEnPantalla()
							.getIdentificator(), areaDeTrabajo
							.getGraphComponent());

				} catch (Exception e) {
					System.out.println("No se pudo exportar el diagrama");
				}
			}
		});

		fileMenu.addSeparator();
		fileMenu.addSeparator();
		// agrego la opcion Salir al menu de archivo y su Listener
		JMenuItem exitMenuItem = new JMenuItem(PantallaConstants.SALIR);
		fileMenu.add(exitMenuItem);

		exitMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				// mainFrame.dispose();
				
				if (controlProyeto.getProyecto()!= null){
					JDialog dialogo = new JDialog(); 
					//default icon, custom title
					int n = JOptionPane.showConfirmDialog(dialogo,
							"Quiere guardar los cambios antes de salir?",
							"Salir", JOptionPane.YES_NO_OPTION);
					if( n == 0)
						controlProyeto.persistirXML();	
				}
				
				System.exit(0);
			}
		});

	}

	private void agregarMenuEditarAHerramientas() {
		// Genero el boton Editar y lo agrego a la barra de herramientas
		JMenu editMenu = new JMenu("Editar");
		menuBar.add(editMenu);

		// agrego la opcion de Deshacer al menu Editar
		editMenu.add(areaDeTrabajo.bind(mxResources.get("undo"),
				new HistoryAction(true),
				"/com/mxgraph/examples/swing/images/undo.gif"));

		// agrego la opcion de Rehacer al menu Editar
		editMenu.add(areaDeTrabajo.bind(mxResources.get("redo"),
				new HistoryAction(false),
				"/com/mxgraph/examples/swing/images/redo.gif"));

		editMenu.addSeparator();

		// agrego la opcion de Cortar al menu Editar
		editMenu.add(areaDeTrabajo.bind(mxResources.get("cut"), TransferHandler
				.getCutAction(), "/com/mxgraph/examples/swing/images/cut.gif"));

		// agrego la opcion de Copiar al menu Editar
		editMenu.add(areaDeTrabajo.bind(mxResources.get("copy"),
				TransferHandler.getCopyAction(),
				"/com/mxgraph/examples/swing/images/copy.gif"));

		// agrego la opcion de Pegar al menu Editar
		editMenu.add(areaDeTrabajo.bind(mxResources.get("paste"),
				TransferHandler.getPasteAction(),
				"/com/mxgraph/examples/swing/images/paste.gif"));

		editMenu.addSeparator();

		// agrego la opcion Eliminar al menu Editar
//		editMenu.add(areaDeTrabajo.bind(mxResources.get("delete"),
//				mxGraphActions.getDeleteAction(),
//				"/com/mxgraph/examples/swing/images/delete.gif"));

		editMenu.addSeparator();

		// agrego la opcion Seleccionar Todo al menu de editar
		editMenu.add(areaDeTrabajo.bind(mxResources.get("selectAll"),
				mxGraphActions.getSelectAllAction()));

		// agrego la opcion Invertir Seleccion al menu de editar y su Listener
		editMenu.add(areaDeTrabajo.bind(mxResources.get("selectNone"),
				mxGraphActions.getSelectNoneAction()));

	}

	private void agregarMenuZoomAHerramientas() {
		// Genero el boton Zoom y lo agrego a la barra de herramientas
		JMenu zoomMenu = new JMenu("Zoom");
		menuBar.add(zoomMenu);

		// agrego la opcion Aumentar al menu de zoom
		zoomMenu.add(areaDeTrabajo.bind(mxResources.get("zoomIn"),
				mxGraphActions.getZoomInAction()));

		// agrego la opcion Disminuir al menu de zoom
		zoomMenu.add(areaDeTrabajo.bind(mxResources.get("zoomOut"),
				mxGraphActions.getZoomOutAction()));

		// agrego la opcion Restaurar Zoom al menu de zoom
		zoomMenu.add(areaDeTrabajo.bind(mxResources.get("page"),
				new ZoomPolicyAction(mxGraphComponent.ZOOM_POLICY_PAGE)));

	}

	private void agregarPackageExplorer() {

		packageExplorer = new ExploradorDeDiagramas();

		scrollPackage = new JScrollPane(packageExplorer.getTree());
		scrollPackage
				.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		scrollPackage
				.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
		mainFrame.getContentPane().add(scrollPackage, BorderLayout.WEST);

	}

	public void actualizarVistaPackageExplorer(Proyecto proyecto, String seleccion) {
		packageExplorer.actualizar(proyecto.getIdentificator(), proyecto
				.getListaDiagramas(), seleccion, controlProyeto.getDiagramaEnPantalla().getListaEntidades());
		// si abro un proyecto o creo uno nuevo, cambio el package explorer
		// y debo limpiar la pantalla de elementos
		limpiarPantalla();
		

	}

	public void actualizarVista(Proyecto proyecto) {

		this.agregarAreaDeTrabajo();
//		this.agregarMenuEditarAHerramientas();
		this.agregarMenuZoomAHerramientas();
		this.agregarMenuEntidadABarraHerramientas();
		this.agregarMenuRelacionABarraHerramientas();
		this.agregarMenuJerarquiaABarraHerramientas();
		this.agregarMenuValidarABarraHerramientas();
		this.agregarMenuDiagramaABarraHerramientas();

		// TODO: Este metodo agrega los nuevos componentes y reacomoda la
		// pantalla
		// al tamanio de la cantidad de componentes que tenga.
		mainFrame.pack();
		mainFrame.setExtendedState(Frame.MAXIMIZED_BOTH);

	}

	private void agregarAreaDeTrabajo() {
		mainFrame.remove(scrollPackage);
		JSplitPane divisor = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
				scrollPackage, areaDeTrabajo);
		divisor.setOneTouchExpandable(true);
		divisor.setDividerLocation(200);
		divisor.setDividerSize(6);
		divisor.setBorder(null);
		mainFrame.getContentPane().add(divisor, BorderLayout.CENTER);
				
	}

	public String elegirArchivo(String cmd) {

		if (this.elegidorArchivo == null)
			this.elegidorArchivo = new ElegidorDeArchivos();
		return this.elegidorArchivo.elegirArchivo(cmd);
	}

	public GraphEditor getAreaParaDibujar() {
		return areaDeTrabajo;
	}

	public void setDiagramaFromPackageExplorer(String diagramaSeleccionado) {
		if(!diagramaSeleccionado.equalsIgnoreCase(controlProyeto.getDiagramaEnPantalla().getIdentificator()))
		{
			// antes de cambiar de diagrama, primero guardo los XML asi no pierdo las posiciones en la pantalla
			//segundo borro los elementos de la pantalla
			//y despues recien ahi cambio de diagrama
			controlProyeto.persistirXML();
			limpiarPantalla();	
			controlProyeto.cambiarDiagrama(diagramaSeleccionado);
			packageExplorer.actualizar(controlProyeto.getProyecto().getIdentificator(),
					controlProyeto.getProyecto().getListaDiagramas(), 
					diagramaSeleccionado, controlProyeto.getDiagramaEnPantalla().getListaEntidades());
			
		}
		
	}

	private void limpiarPantalla() {
		mxGraph graph =   this.areaDeTrabajo.getGraphComponent().getGraph();
//		graph.removeCells(graph.getChildVertices(graph.getDefaultParent()));
		
		graph.selectAll();
		graph.removeCells(graph.getSelectionCells());
	}

	public GraphEditor getAreaDeTrabajo() {
		return areaDeTrabajo;
	}

	public void setAreaDeTrabajo(GraphEditor areaDeTrabajo) {
		this.areaDeTrabajo = areaDeTrabajo;
	}

	public ExploradorDeDiagramas getPackageExplorer() {
		return packageExplorer;
	}

	public Object dibujarEntidadesEnPantalla(Entidad entidad, Coordenada coordenada){
		return ManagerAreaDeTrabajo.getInstance().dibujarEntidad(entidad, coordenada);
	}

	
	public void dibujarJerarquiasEnPantalla(Jerarquia jerarquia) {
		ManagerAreaDeTrabajo.getInstance().dibujarJerarquia(jerarquia);
		
	}
	
	public Object dibujarRelacionesEnPantalla(Relacion relacion,Coordenada coordenada) {
		return ManagerAreaDeTrabajo.getInstance().dibujarRelacion(relacion, coordenada);
		
	}
	
	public Object dibujarAtributoSimpleEnPantalla(Object entidad, Atributo atributo, Coordenada coordenada, String nombreConReferencia){
		return ManagerAreaDeTrabajo.getInstance().dibujarAtributo(entidad, atributo, coordenada,nombreConReferencia);
	}
	
	public Object dibujarAtributoCompuestoEnPantalla(Object elemento, AtributoCompuesto atributoCompuesto, Coordenada coordenada,String referenciaAlElementoOrigen){
		return ManagerAreaDeTrabajo.getInstance().dibujarAtributoCompuesto(elemento, atributoCompuesto, coordenada, referenciaAlElementoOrigen);
		
	}
}
